﻿using System.Data.Common;
using NAnt.Core;
using NAnt.Core.Attributes;
using NHibernate;
using NHibernate.Cfg;
using Sentient.Core;

namespace Sentient.Nant.Tasks
{
    public abstract class NHibernateTask : Task
    {
        private string _assembly;
        private string _catalog;
        private Configuration _config;
        private string _dataSource = "localhost";
        private NHibernateBuilder _nhibernateBuilder;
        private ISession _session;
        private ISessionFactory _sessionFactory;

        #region NAnt Properties

        /// <summary>
        /// Gets or sets the datasource
        /// </summary>
        /// <value>The datasource</value>
        [TaskAttribute("datasource", Required = false)]
        public string DataSource
        {
            get { return _dataSource; }
            set { _dataSource = value; }
        }

        /// <summary>
        /// Gets or sets the catalog
        /// </summary>
        /// <value>The catalog</value>
        [TaskAttribute("catalog", Required = false)]
        public string Catalog
        {
            get { return _catalog; }
            set { _catalog = value; }
        }

        /// <summary>
        /// Gets or sets the assemblies load with embedded *.hbm.xml resources.
        /// </summary>
        /// <value>The assemblies.</value>
        [TaskAttribute("assembly", Required = false)]
        public string Assembly
        {
            get { return _assembly; }
            set { _assembly = value; }
        }

        #endregion

        protected override void ExecuteTask()
        {
            using (Session)
            using (var transaction = Session.BeginTransaction())
            {
                ExecuteInTransaction();

                transaction.Commit();
            }
        }

        protected virtual void ExecuteInTransaction()
        {
        }

        protected DbConnectionStringBuilder ConnectionString
        {
            get { return NHibernateBuilder.ConnectionString; }
        }

        protected Configuration NHConfig
        {
            get
            {
                if (_config == null)
                    _config = NHibernateBuilder.Configuration;
                return _config;
            }
        }

        protected ISessionFactory SessionFactory
        {
            get
            {
                if (_sessionFactory == null)
                    _sessionFactory = NHConfig.BuildSessionFactory();
                return _sessionFactory;
            }
        }

        protected ISession Session
        {
            get
            {
                if (_session == null)
                    _session = SessionFactory.OpenSession();
                return _session;
            }
        }

        private NHibernateBuilder NHibernateBuilder
        {
            get
            {
                if (_nhibernateBuilder == null)
                    _nhibernateBuilder = new NHibernateBuilder(DataSource, Catalog, Assembly);
                return _nhibernateBuilder;
            }
        }

        protected void RunSqlCommand(string sql)
        {
            Session.CreateSQLQuery(sql).List();
        }
    }
}